﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using EricUtility.Windows.Forms;
using WatchSeriesHelper.Entities;
using TVOnline;
using TVOnline.VideoViewing;
using TVOnline.Windows.Forms;
using WatchSeriesHelper.Persistance;
using TVOnline.Entities;
using System.Diagnostics;
using EricUtility;
using EricUtility.Networking.Gathering;

namespace WatchSeriesHelper.Windows.Forms
{
    public delegate void TabPageEventHandler(TabPage t);
    public partial class WatchSeriesTabContent : TabPageContent
    {
        public bool syncRunning = false;
        public bool syncOnHold = false;
        public bool skipEpisodeLoad = false;
        public int oldEpisodeLoaded = -1;
        public event TabPageEventHandler AskForANewTab = delegate { };
        private string oldLetter;
        private Dictionary<string, LetterInfo> letters = new Dictionary<string, LetterInfo>();
        private Dictionary<KnownWebsite, CheckBox> btnKnowns = new Dictionary<KnownWebsite, CheckBox>();
        private List<string> todayAll = new List<string>();
        public WatchSeriesTabContent()
        {
            InitializeComponent();
            btnKnowns.Add(KnownWebsite.MegaVideo, btnMegaVideo);
            btnKnowns.Add(KnownWebsite.WiseVid, btnWiseVid);
            btnKnowns.Add(KnownWebsite.ZShare, btnZShare);
            btnKnowns.Add(KnownWebsite.SockShare, btnSockShare);
            btnKnowns.Add(KnownWebsite.Divxstage, btnDivxStage);
            btnKnowns.Add(KnownWebsite.MovShare, btnMovShare);
            btnKnowns.Add(KnownWebsite.PlayHD, btnPlayHD);
            btnKnowns.Add(KnownWebsite.PutLocker, btnPutLocker);
            btnKnowns.Add(KnownWebsite.StageVu, btnStageVu);
            btnKnowns.Add(KnownWebsite.Tudou, btnTudou);
            WatchSeriesTabContent_Resize(this, null);

        }

        private void btnLetter_Click(object sender, EventArgs e)
        {
            statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.Waiting;
            Button btnSender = sender as Button;
            string letter = btnSender.Text;
            if (!String.IsNullOrEmpty(oldLetter))
                pnlLetters.Controls["btn" + oldLetter].Enabled = true;
            oldLetter = letter == "#" ? "09" : letter;
            btnSender.Enabled = false;
            if (!letters.ContainsKey(letter))
                letters.Add(letter, new LetterInfo(letter));
            lstFavs.SelectedIndex = -1;
            lstSerie.Items.Clear();
            lstSeason.Items.Clear();
            lstEpisode.Items.Clear();
            lstWebSite.Items.Clear();
            foreach (CheckBox c in btnKnowns.Values)
            {
                c.Enabled = false;
                c.Checked = false;
            }
            btnMagic.Enabled = false;
            btnAddFavs.Enabled = false;
            btnRemoveFavs.Enabled = false;
            btnRefresh.Enabled = false;
            lstMirror.Items.Clear();
            lstLink.Items.Clear();
            tabctlShow.Visible = false;
            lblTitLastViewed.Visible = false;
            lblLastViewed.Visible = false;
            grpEpisodeDesc.Visible = false;
            Enabled = false;
            new Thread(new ParameterizedThreadStart(LoadLetter)).Start(letters[letter]);
        }

        private void lstSerie_SelectedIndexChanged(object sender, EventArgs e)
        {
            ListBox lstSender = sender as ListBox;
            if (lstSender != null && lstSender.SelectedIndex >= 0)
            {
                TVShowInfo ts = lstSender.SelectedItem as TVShowInfo;
                if (lstSender != lstSerie)
                {
                    lstSerie.SelectedIndex = -1;
                    btnAddFavs.Enabled = false;
                    btnRemoveFavs.Enabled = true;
                }
                if (lstSender != lstFavs)
                {
                    lstFavs.SelectedIndex = -1;
                    bool canAdd = true;
                    foreach (TVShowInfo t in lstFavs.Items)
                        if (ts.Id == t.Id)
                            canAdd = false;
                    btnAddFavs.Enabled = canAdd;
                    btnRemoveFavs.Enabled = false;
                }
                statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.Waiting;
                lstSeason.Items.Clear();
                lstEpisode.Items.Clear();
                lstWebSite.Items.Clear();
                foreach (CheckBox c in btnKnowns.Values)
                {
                    c.Enabled = false;
                    c.Checked = false;
                }
                btnMagic.Enabled = false;
                grpEpisodeDesc.Visible = false;
                lstMirror.Items.Clear();
                lstLink.Items.Clear();
                Enabled = false;
                new Thread(new ParameterizedThreadStart(LoadSerie)).Start(lstSender.SelectedItem);
            }
        }

        private void lstSeason_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lstSeason.SelectedIndex >= 0)
            {
                SeasonInfo ts = (SeasonInfo)lstSeason.SelectedItem;
                lstEpisode.Items.Clear();
                lstWebSite.Items.Clear();
                foreach (CheckBox c in btnKnowns.Values)
                {
                    c.Enabled = false;
                    c.Checked = false;
                }
                btnMagic.Enabled = false;
                grpEpisodeDesc.Visible = false;
                lstMirror.Items.Clear();
                lstLink.Items.Clear();
                foreach (EpisodeInfo te in ts.Episodes)
                {
                    lstEpisode.Items.Add(te);
                }
                if (ts.Episodes.Length == 1)
                {
                    lstEpisode.SelectedIndex = 0;
                }
            }
        }

        private void lstEpisode_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (skipEpisodeLoad)
                skipEpisodeLoad = false;
            else if (lstEpisode.SelectedIndex >= 0)
            {
                statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.Waiting;
                lstWebSite.Items.Clear();
                foreach (CheckBox c in btnKnowns.Values)
                {
                    c.Enabled = false;
                    c.Checked = false;
                }
                btnMagic.Enabled = false;
                lstMirror.Items.Clear();
                lstLink.Items.Clear();
                Enabled = false;
                new Thread(new ParameterizedThreadStart(LoadEpisode)).Start(lstEpisode.SelectedItem);
            }
        }

        private void lstWebSite_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lstWebSite.SelectedIndex >= 0)
            {
                foreach (CheckBox c in btnKnowns.Values)
                    c.Checked = false;
                lstMirror.Items.Clear();
                lstLink.Items.Clear();
                btnMagic.Enabled = false;
                WebsiteInfo tw = (WebsiteInfo)lstWebSite.SelectedItem;
                foreach (LinkInfo tm in tw.Mirrors)
                {
                    lstMirror.Items.Add(tm);
                }
                //if (tw.Mirrors.Length == 1)
                //{
                lstMirror.SelectedIndex = 0;
                //}
            }
        }
        private void KnownWebSiteClick(KnownWebsite t)
        {
            foreach (KeyValuePair<KnownWebsite, CheckBox> kvp in btnKnowns)
                kvp.Value.Checked = (t == kvp.Key);
            if (lstEpisode.SelectedIndex >= 0)
            {
                EpisodeInfo te = (EpisodeInfo)lstEpisode.SelectedItem;
                WebsiteInfo tw = te.KnownWebSite(t);
                if (tw != null)
                {
                    lstWebSite.SelectedIndex = -1;
                    lstMirror.Items.Clear();
                    lstLink.Items.Clear();
                    btnMagic.Enabled = false;
                    foreach (LinkInfo tm in tw.Mirrors)
                    {
                        lstMirror.Items.Add(tm);
                    }
                    //if (tw.Mirrors.Length == 1)
                    //{
                    lstMirror.SelectedIndex = 0;
                    //}
                }
            }
        }
        private void btnMegaVideo_Click(object sender, EventArgs e)
        {
            KnownWebSiteClick(KnownWebsite.MegaVideo);
        }

        private void btnWiseVid_Click(object sender, EventArgs e)
        {
            KnownWebSiteClick(KnownWebsite.WiseVid);
        }

        private void btnZShare_Click(object sender, EventArgs e)
        {
            KnownWebSiteClick(KnownWebsite.ZShare);
        }

        private void btnVideoWeed_Click(object sender, EventArgs e)
        {
            KnownWebSiteClick(KnownWebsite.SockShare);
        }

        private void btnYouTube_Click(object sender, EventArgs e)
        {
            KnownWebSiteClick(KnownWebsite.Divxstage);
        }

        private void btnMovShare_Click(object sender, EventArgs e)
        {
            KnownWebSiteClick(KnownWebsite.MovShare);
        }

        private void btnPlayHD_Click(object sender, EventArgs e)
        {
            KnownWebSiteClick(KnownWebsite.PlayHD);
        }

        private void btnNovaMov_Click(object sender, EventArgs e)
        {
            KnownWebSiteClick(KnownWebsite.PutLocker);
        }

        private void btnStageVu_Click(object sender, EventArgs e)
        {
            KnownWebSiteClick(KnownWebsite.StageVu);
        }

        private void btnTudou_Click(object sender, EventArgs e)
        {
            KnownWebSiteClick(KnownWebsite.Tudou);
        }

        private void lstMirror_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lstMirror.SelectedIndex >= 0)
            {
                lstLink.Items.Clear();
                btnMagic.Enabled = false;
                LinkInfo tw = (LinkInfo)lstMirror.SelectedItem;
                foreach (LinkPartInfo tl in tw.Links)
                {
                    lstLink.Items.Add(tl);
                }
                if (tw.Links.Length >= 1)
                {
                    lstLink.SelectedIndex = 0;
                }
            }
        }

        private void lstLink_SelectedIndexChanged(object sender, EventArgs e)
        {
            btnMagic.Enabled = (lstLink.SelectedIndex >= 0);
            if (lstLink.SelectedIndex >= 0)
            {
                statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.Waiting;
                Enabled = false;
                new Thread(new ParameterizedThreadStart(LoadLink)).Start(lstLink.SelectedItem);
            }
        }

        public void LoadLetter(object state)
        {
            AbstractSerieList tl = (AbstractSerieList)state;
            try
            {
                tl.LoadIfNeeded();
                EndLoadLetter(tl);
            }
            catch
            {
                EndLoadLetterBadly(tl);
            }
        }

        public void LoadSerie(object state)
        {
            TVShowInfo ts = (TVShowInfo)state;
            try
            {
                ts.LoadIfNeeded();
                EndLoadSerie(ts);
            }
            catch
            {
                EndLoadSerieBadly(ts);
            }
        }

        public void LoadEpisode(object state)
        {
            EpisodeInfo te = (EpisodeInfo)state;
            try
            {
                te.LoadIfNeeded();
                EndLoadEpisode(te);
            }
            catch( Exception e )
            {
                EndLoadEpisodeBadly(te);
            }
        }

        public void LoadLink(object state)
        {
            LinkPartInfo tl = (LinkPartInfo)state;
            try
            {
                tl.LoadIfNeeded();
                EndLoadLink(tl);
            }
            catch
            {
                EndLoadLinkBadly(tl);
            }
        }

        public void WatchLink(object state)
        {
            LinkPartInfo tl = (LinkPartInfo)state;
            try
            {
                tl.LoadViewer();
                EndWatchLink(tl.Viewer);
            }
            catch
            {
                EndWatchLinkBadly(null);
            }
        }

        public delegate void TupleWatchLinkHandler(AbstractViewer viewer);
        private void EndWatchLink(AbstractViewer viewer)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new TupleWatchLinkHandler(EndWatchLink), new object[] { viewer });
                return;
            }
            MarkWatched();
            SeasonInfo s = lstSeason.SelectedItem as SeasonInfo;
            EpisodeInfo ep = lstEpisode.SelectedItem as EpisodeInfo;
            string title = String.Format("S{0:00}E{1:00}", s.SeasonId, ep.EpisodeId);
            if (viewer is ErrorViewer)
            {
                MessageBox.Show(((ErrorViewer)viewer).Error, title, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else if (viewer is WebBrowserViewer)
            {
                WebBrowserViewer v = viewer as WebBrowserViewer;
                CustomizedTabPage t = new CustomizedTabPage(new WebBrowserTabContent(v.ViewUrl, v.Url));
                t.Text = title;
                AskForANewTab(t);
            }
            else if (viewer is FlashViewer)
            {
                FlashViewer v = viewer as FlashViewer;
                CustomizedTabPage t = new CustomizedTabPage(new FlashMovieTabContent(v.Movie, v.FlashVars, v.Url));
                t.Text = title;
                AskForANewTab(t);
            }
            else if (viewer is FlashPlayerViewer)
            {
                FlashPlayerViewer v = viewer as FlashPlayerViewer;
                CustomizedTabPage t = new CustomizedTabPage(new CustomizedFlashMovieTabContent(v.Player, v.Movie, v.DownloadLink, v.Url));
                t.Text = title;
                AskForANewTab(t);
            }
            else if (viewer is DivxPlayerViewer)
            {
                DivxPlayerViewer v = viewer as DivxPlayerViewer;
                CustomizedTabPage t = new CustomizedTabPage(new DivxDownloadTabContent(v.DownloadLink, v.Url));
                t.Text = title;
                AskForANewTab(t);
            }
            else
                System.Diagnostics.Process.Start(viewer.Url);
            statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.None;
            Enabled = true;
        }

        private void EndWatchLinkBadly(AbstractViewer viewer)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new TupleWatchLinkHandler(EndWatchLinkBadly), new object[] { viewer });
                return;
            }
            statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.Bad;
            Enabled = true;
        }

        public delegate void TupleLetterHandler(AbstractSerieList tl);
        public void EndLoadLetter(AbstractSerieList tl)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new TupleLetterHandler(EndLoadLetter), new object[] { tl });
                return;
            }
            foreach (TVShowInfo ts in tl.Series)
            {
                lstSerie.Items.Add(ts);
            }
            statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.None;
            Enabled = true;
            if (tl.Series.Length == 1)
            {
                lstSerie.SelectedIndex = 0;
            }
        }
        public void EndLoadLetterBadly(AbstractSerieList tl)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new TupleLetterHandler(EndLoadLetterBadly), new object[] { tl });
                return;
            }
            statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.Bad;
            if (!String.IsNullOrEmpty(oldLetter))
                Controls["btn" + oldLetter].Enabled = true;
            oldLetter = "";
            Enabled = true;
        }

        public delegate void TupleShowHandler(TVShowInfo tl);
        public void EndLoadSerie(TVShowInfo ts)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new TupleShowHandler(EndLoadSerie), new object[] { ts });
                return;
            }
            foreach (SeasonInfo s in ts.Seasons)
            {
                lstSeason.Items.Add(s);
            }
            btnRefresh.Enabled = true;
            statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.None;
            RefreshShowDesc(ts);
            Enabled = true;
            if (lstFavs.SelectedIndex >= 0)
                PersistFavs.SaveFavShows(lstFavs.Items);
            if (ts.Seasons.Length == 1)
            {
                lstSeason.SelectedIndex = 0;
            }
        }
        public void EndLoadSerieBadly(TVShowInfo ts)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new TupleShowHandler(EndLoadSerieBadly), new object[] { ts });
                return;
            }
            statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.Bad;
            lstSerie.SelectedIndex = -1;
            lstFavs.SelectedIndex = -1;
            btnAddFavs.Enabled = false;
            btnRemoveFavs.Enabled = false;
            Enabled = true;
        }

        public delegate void TupleEpisodeHandler(EpisodeInfo tl);
        public void EndLoadEpisode(EpisodeInfo te)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new TupleEpisodeHandler(EndLoadEpisode), new object[] { te });
                return;
            }
            foreach (WebsiteInfo tw in te.WebSites)
            {
                if (!btnKnowns.ContainsKey(tw.TypeWebSite))
                    lstWebSite.Items.Add(tw);
            }
            foreach (KeyValuePair<KnownWebsite, CheckBox> kvp in btnKnowns)
                kvp.Value.Enabled = (te.KnownWebSite(kvp.Key) != null);
            statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.None;
            grpEpisodeDesc.Visible = true;
            grpEpisodeDesc.Text = String.Format("S{0:00}E{1:00}  {2}", te.Season.SeasonId, te.EpisodeId, te.Name);
            lblEpisodeDesc.Text = te.Description;
            Enabled = true;
            if (te.WebSites.Length == 1 && lstWebSite.Items.Count == 1)
            {
                lstWebSite.SelectedIndex = 0;
            }
        }
        public void EndLoadEpisodeBadly(EpisodeInfo ts)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new TupleEpisodeHandler(EndLoadEpisodeBadly), new object[] { ts });
                return;
            }
            statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.Bad;
            lstEpisode.SelectedIndex = -1;
            Enabled = true;
        }

        public delegate void TupleLinkHandler(LinkPartInfo tl);
        public void EndLoadLink(LinkPartInfo tl)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new TupleLinkHandler(EndLoadLink), new object[] { tl });
                return;
            }
            statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.None;
            Enabled = true;
        }
        public void EndLoadLinkBadly(LinkPartInfo tl)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new TupleLinkHandler(EndLoadLinkBadly), new object[] { tl });
                return;
            }
            statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.Bad;
            lstLink.SelectedIndex = -1;
            Enabled = true;
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            foreach (TVShowInfo t in PersistFavs.LoadFavShows())
                lstFavs.Items.Add(t);
            new Thread(new ThreadStart(loadTvToday)).Start();
            timerToday.Start();
        }

        private void btnMagic_Click(object sender, EventArgs e)
        {
            if (lstLink.SelectedIndex >= 0)
            {
                statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.Waiting;
                Enabled = false;
                new Thread(new ParameterizedThreadStart(WatchLink)).Start(lstLink.SelectedItem);
            }
        }

        private void btnAddFavs_Click(object sender, EventArgs e)
        {
            if (lstSerie.SelectedIndex >= 0)
            {
                TVShowInfo si = (TVShowInfo)lstSerie.SelectedItem;
                if (String.IsNullOrEmpty(si.EpGuideId))
                    si.EpGuideId = SelectGuide(si.Name);
                lstFavs.Items.Add(si);
                PersistFavs.SaveFavShows(lstFavs.Items);
            }
        }

        private void btnRemoveFavs_Click(object sender, EventArgs e)
        {
            if (lstFavs.SelectedIndex >= 0)
            {
                lstFavs.Items.Remove(lstFavs.SelectedItem);
                lstSeason.Items.Clear();
                lstEpisode.Items.Clear();
                lstWebSite.Items.Clear();
                foreach (CheckBox c in btnKnowns.Values)
                {
                    c.Enabled = false;
                    c.Checked = false;
                }
                btnMagic.Enabled = false;
                btnAddFavs.Enabled = false;
                btnRemoveFavs.Enabled = false;
                btnRefresh.Enabled = false;
                grpEpisodeDesc.Visible = false;
                tabctlShow.Visible = false;
                lblTitLastViewed.Visible = false;
                lblLastViewed.Visible = false;
                lstMirror.Items.Clear();
                lstLink.Items.Clear();
                PersistFavs.SaveFavShows(lstFavs.Items);
            }
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            ListBox lst = null;
            if (lstSerie.SelectedIndex >= 0)
                lst = lstSerie;
            else if (lstFavs.SelectedIndex >= 0)
                lst = lstFavs;
            if (lst != null)
            {
                TVShowInfo info = lst.SelectedItem as TVShowInfo;
                if (info != null)
                {
                    if (info.TvRage != null)
                        info.TvRage.NeedToReload();
                    info.NeedToReload();
                    lstSerie_SelectedIndexChanged(lst, e);
                }
            }
        }

        private void btnEpisodeBrowser_Click(object sender, EventArgs e)
        {
            if (lstEpisode.SelectedIndex >= 0)
            {
                EpisodeInfo ei = (EpisodeInfo)lstEpisode.SelectedItem;
                Process.Start(ei.URL);
                ctxtEpisode_Ended();
            }
        }
        private void MarkWatched()
        {
            SeasonInfo s = lstSeason.SelectedItem as SeasonInfo;
            EpisodeInfo ep = lstEpisode.SelectedItem as EpisodeInfo;
            ep.Season.Show.LastSeasonViewed = s.SeasonId;
            ep.Season.Show.LastEpisodViewed = ep.EpisodeId;
            PersistFavs.SaveFavShows(lstFavs.Items);
            lblTitLastViewed.Visible = !String.IsNullOrEmpty(s.Show.LastViewed);
            lblLastViewed.Text = s.Show.LastViewed;
            lstEpisode.Refresh();
            lstSeason.Refresh();
            lstFavs.Refresh();
        }

        private void btnMarkEpisodeWatched_Click(object sender, EventArgs e)
        {
            MarkWatched();
            ctxtEpisode_Ended();
        }

        private void lstEpisode_MouseDown(object sender, MouseEventArgs e)
        {
            int indexover = lstEpisode.IndexFromPoint(e.X, e.Y);
            if (indexover >= 0 && indexover < lstEpisode.Items.Count)
            {
                if (e.Button == System.Windows.Forms.MouseButtons.Right)
                {
                    oldEpisodeLoaded = lstEpisode.SelectedIndex;
                    skipEpisodeLoad = true;
                }
                lstEpisode.SelectedIndex = indexover;
            }
        }

        private void ctxtEpisode_Opening(object sender, CancelEventArgs e)
        {
            if (lstEpisode.SelectedIndex < 0)
                e.Cancel = true;
        }

        private void btnTvToday_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            String all = "";
            foreach (string s in todayAll)
                all += s + '\n';
            MessageBox.Show(all, "TV TODAY", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        public delegate void VisibilityHandler(bool vis);
        private void ChangeTvTodayVisibility(bool vis)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new VisibilityHandler(ChangeTvTodayVisibility), new object[] { vis });
                return;
            }
            btnTvToday.Visible = vis;
        }
        public delegate void EmptyHandler();
        private void WriteTodayFavs()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new EmptyHandler(WriteTodayFavs), new object[] { });
                return;
            }
            lblToday.Text = "";
            foreach (string s in todayAll)
            {
                foreach (object o in lstFavs.Items)
                {
                    if (s.Contains(o.ToString()))
                        lblToday.Text += s.Remove(s.LastIndexOf("-")) + "     ";
                }
            }
        }
        private void RefreshFavs()
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new EmptyHandler(RefreshFavs), new object[] { });
                return;
            }
            lstFavs.Refresh();
        }
        public delegate string String2Handler(string s);
        private string SelectGuide(string s)
        {
            //if (this.InvokeRequired)
            //{
            //    return (string)this.Invoke(new String2Handler(SelectGuide), new object[] { s });
            //}
            //string useless = "(a Titles & Air Dates Guide)";
            s = s
                .Replace(" and ", " ")
                .Replace(" or ", " ")
                .Replace(" & ", " ");

            List<SearchResultEntry> entries = SearchingUtility.GoogleSearch(WebStringUtility.EncodeUrl("allintitle: site:epguides.com \"" + TVShowInfo.EPGUIDE_USELESS + "\" " + s));
            if (entries.Count > 1)
            {
                ChooseEpGuideForm form = new ChooseEpGuideForm(s, entries);
                form.ShowDialog();
                return form.Result;
            }
            else if (entries.Count == 1)
                return entries[0].Url.Replace("http://epguides.com/", "").Replace("/", "");
            return TVShowInfo.NO_EPGUIDE;
        }
        public delegate void StringHandler(string s);
        private void UpdateStatus(string s)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new StringHandler(UpdateStatus), new object[] { s });
                return;
            }
            lblStatusDesc.Text = "Synchronizing ... " + s;
        }
        private void Synchronizing(bool vis)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new VisibilityHandler(Synchronizing), new object[] { vis });
                return;
            }
            UpdateStatus("");
            lblStatusDesc.Visible = vis;
            syncRunning = vis;
            lblStatusPic.BackgroundImage = (syncOnHold ? EricUtility.Windows.Forms.Properties.Resources.bad : (syncRunning ? WatchSeriesHelper.Properties.Resources.refreshSmall : null));
        }
        private void loadTvToday()
        {
            //try
            //{
                if (syncRunning)
                    return;
                Synchronizing(true);
                ChangeTvTodayVisibility(false);
                todayAll.Clear();
                string src = EricUtility.Networking.Gathering.GatheringUtility.GetPageSource("http://watchseries.eu/tvschedule/0");
                if (!String.IsNullOrEmpty(src))
                {
                    string content = StringUtility.Extract(src, "<div id=\"left\"", "</ul>") + StringUtility.Extract(src, "<div id=\"right\"", "</ul>");
                    src = src.Substring(src.IndexOf("<h2 class=\"listbig\">"));
                    int last = 0;
                    do
                    {
                        string deb = "<a href=";
                        int ideb = content.IndexOf(deb, last) + deb.Length;
                        if (ideb < deb.Length)
                            break;
                        string fin = "</a>";
                        int ideb2 = content.IndexOf(">", ideb) + 1;
                        last = content.IndexOf(fin, ideb2);
                        string title = content.Substring(ideb2, last - ideb2).Replace("\n","");
                        todayAll.Add(title);
                    } while (true);
                    todayAll.Sort();
                    ChangeTvTodayVisibility(true);
                    WriteTodayFavs();
                    foreach (TVShowInfo si in getFavs())
                    {
                        UpdateStatus(si.Name);
                        if (syncOnHold)
                            break;
                        if (String.IsNullOrEmpty(si.EpGuideId))
                            si.EpGuideId = SelectGuide(si.Name);
                        si.ForceLoad();
                        RefreshFavs();
                    }
                    PersistFavs.SaveFavShows(lstFavs.Items);
                    if (!syncOnHold)
                        Synchronizing(false);
                }
            //}
            //catch(Exception e)
            //{
            //    MessageBox.Show(e.StackTrace, e.ToString());
            //}
        }

        private void timerToday_Tick(object sender, EventArgs e)
        {
            new Thread(new ThreadStart(loadTvToday)).Start();
        }

        private void lstEpisode_DrawItem(object sender, DrawItemEventArgs e)
        {
            e.DrawBackground();
            if (e.Index >= 0 && lstEpisode.Items.Count > e.Index)
            {
                EpisodeInfo ei = lstEpisode.Items[e.Index] as EpisodeInfo;
                bool isNew = true;
                if (ei.Season.Show.LastSeasonViewed == -1)
                    isNew = true;
                else if (ei.Season.Show.LastEpisodViewed == -1)
                    isNew = true;
                else if (ei.Season.SeasonId < ei.Season.Show.LastSeasonViewed)
                    isNew = false;
                else if (ei.Season.Show.LastSeasonViewed == ei.Season.SeasonId && ei.EpisodeId <= ei.Season.Show.LastEpisodViewed)
                    isNew = false;


                e.Graphics.DrawString(ei.ToString(), new Font("Microsoft Sans Serif", 8.25F, isNew ? FontStyle.Bold : FontStyle.Regular), Brushes.Black, e.Bounds);
            }
            e.DrawFocusRectangle();
        }

        private void lstSeason_DrawItem(object sender, DrawItemEventArgs e)
        {
            e.DrawBackground();
            if (e.Index >= 0 && lstSeason.Items.Count > e.Index)
            {
                SeasonInfo si = lstSeason.Items[e.Index] as SeasonInfo;
                bool isNew = true;
                if (si.Show.LastSeasonViewed == -1)
                    isNew = true;
                else if (si.Show.LastEpisodViewed == -1)
                    isNew = true;
                else if (si.SeasonId < si.Show.LastSeasonViewed)
                    isNew = false;
                else if (si.SeasonId == si.Show.LastSeasonViewed && si.Episodes[si.Episodes.Length - 1].EpisodeId <= si.Show.LastEpisodViewed)
                    isNew = false;


                e.Graphics.DrawString(si.ToString(), new Font("Microsoft Sans Serif", 8.25F, isNew ? FontStyle.Bold : FontStyle.Regular), Brushes.Black, e.Bounds);
            }
            e.DrawFocusRectangle();
        }

        private void lstFavs_DrawItem(object sender, DrawItemEventArgs e)
        {
            e.DrawBackground();
            if (e.Index >= 0 && lstFavs.Items.Count > e.Index)
            {
                TVShowInfo si = lstFavs.Items[e.Index] as TVShowInfo;
                bool isNew = true;
                if (si.LastSeasonViewed == -1)
                    isNew = true;
                else if (si.LastEpisodViewed == -1)
                    isNew = true;
                else if (si.Seasons.Length <= 0)
                    isNew = false;
                else if (si.Seasons[si.Seasons.Length - 1].SeasonId < si.LastSeasonViewed)
                    isNew = false;
                else if (si.LastSeasonViewed == si.Seasons[si.Seasons.Length - 1].SeasonId && si.Seasons[si.Seasons.Length - 1].Episodes[si.Seasons[si.Seasons.Length - 1].Episodes.Length - 1].EpisodeId <= si.LastEpisodViewed)
                    isNew = false;


                e.Graphics.DrawString(si.ToString(), new Font("Microsoft Sans Serif", 8.25F, isNew ? FontStyle.Bold : FontStyle.Regular), Brushes.Black, e.Bounds);
            }
            e.DrawFocusRectangle();
        }
        public delegate List<TVShowInfo> FavsHandler();
        private List<TVShowInfo> getFavs()
        {
            if (this.InvokeRequired)
            {
                return (List<TVShowInfo>)this.Invoke(new FavsHandler(getFavs), new object[] { });
            }
            List<TVShowInfo> res = new List<TVShowInfo>();
            foreach (object o in lstFavs.Items)
                res.Add((TVShowInfo)o);
            return res;
        }

        private void lblStatusPic_MouseEnter(object sender, EventArgs e)
        {
            Cursor = Cursors.Hand;
        }

        private void lblStatusPic_MouseLeave(object sender, EventArgs e)
        {
            Cursor = Cursors.Default;
        }

        private void lblStatusPic_Click(object sender, EventArgs e)
        {
            if (syncOnHold)
            {
                lblStatusDesc.Text = "Synchronizing ...";
                lblStatusDesc.Visible = false;
                syncOnHold = false;
                new Thread(new ThreadStart(loadTvToday)).Start();
                timerToday.Start();
            }
            else
            {
                syncOnHold = true;
                lblStatusPic.BackgroundImage = EricUtility.Windows.Forms.Properties.Resources.bad;
                lblStatusDesc.Text = "Synchronization cancelled. Click on the 'X' bottom left of the form to reactivate.";
                lblStatusDesc.Visible = true;
                timerToday.Stop();
            }
        }

        private void ctxtEpisode_Ended()
        {
                if (lstEpisode.SelectedIndex != oldEpisodeLoaded)
                {
                    skipEpisodeLoad = true;
                    lstEpisode.SelectedIndex = oldEpisodeLoaded;
                }
                skipEpisodeLoad = false;
                oldEpisodeLoaded = -1;
        }

        private void WatchSeriesTabContent_Resize(object sender, EventArgs e)
        {
            SuspendLayout();
            const int allBaseWidth = 846;
            int diff = Width - allBaseWidth;

            // Descriptions
            const int descBaseWidth = 413;
            const int descEpX = 427;
            int descDelta = (diff / 2);
            tabctlShow.Size = new Size(descBaseWidth + descDelta, tabctlShow.Height);
            //grpShowDesc.Size = new Size(descBaseWidth + descDelta, grpShowDesc.Height);
            grpEpisodeDesc.Size = new Size(descBaseWidth + descDelta, grpEpisodeDesc.Height);
            grpEpisodeDesc.Location = new Point(descEpX + descDelta, grpEpisodeDesc.Top);

            // Letters
            pnlLetters.Location = new Point(((Width / 2) - (pnlLetters.Width / 2)) - 36, pnlLetters.Top);

            int rowDelta = (diff / 5);

            // Row Mirrors
            const int mirrorBaseWidth = 160;
            const int mirrorX = 678;
            int mirrorOffset = (4 * rowDelta);
            lblTitMirrors.Size = new Size(mirrorBaseWidth + rowDelta, lblTitMirrors.Height);
            lblTitMirrors.Location = new Point(mirrorX + mirrorOffset, lblTitMirrors.Top);
            lblTitParts.Size = new Size(mirrorBaseWidth + rowDelta, lblTitParts.Height);
            lblTitParts.Location = new Point(mirrorX + mirrorOffset, lblTitParts.Top);
            lstMirror.Size = new Size(mirrorBaseWidth + rowDelta, lstMirror.Height);
            lstMirror.Location = new Point(mirrorX + mirrorOffset, lstMirror.Top);
            lstLink.Size = new Size(mirrorBaseWidth + rowDelta, lstLink.Height);
            lstLink.Location = new Point(mirrorX + mirrorOffset, lstLink.Top);
            btnMagic.Size = new Size(mirrorBaseWidth + rowDelta, btnMagic.Height);
            btnMagic.Location = new Point(mirrorX + mirrorOffset, btnMagic.Top);

            // Row Websites
            const int websiteBaseWidth = 162;
            const int websiteX = 510;
            int websiteOffset = (3 * rowDelta);
            lblTitWebsite.Size = new Size(websiteBaseWidth + rowDelta, lblTitWebsite.Height);
            lblTitWebsite.Location = new Point(websiteX + websiteOffset, lblTitWebsite.Top);
            lstWebSite.Size = new Size(websiteBaseWidth + rowDelta, lstWebSite.Height);
            lstWebSite.Location = new Point(websiteX + websiteOffset, lstWebSite.Top);
            foreach (CheckBox btn in btnKnowns.Values)
            {
                btn.Size = new Size(websiteBaseWidth + rowDelta, btn.Height);
                btn.Location = new Point(websiteX + websiteOffset, btn.Top);
            }

            // Row Episode & Season
            const int episodeBaseWidth = 162;
            const int episodeX = 342;
            int episodeOffset = (2 * rowDelta);
            lblTitSeasons.Size = new Size(episodeBaseWidth + rowDelta, lblTitSeasons.Height);
            lblTitSeasons.Location = new Point(episodeX + episodeOffset, lblTitSeasons.Top);
            lstSeason.Size = new Size(episodeBaseWidth + rowDelta, lstSeason.Height);
            lstSeason.Location = new Point(episodeX + episodeOffset, lstSeason.Top);
            lblTitEpisode.Size = new Size(episodeBaseWidth + rowDelta, lblTitEpisode.Height);
            lblTitEpisode.Location = new Point(episodeX + episodeOffset, lblTitEpisode.Top);
            lstEpisode.Size = new Size(episodeBaseWidth + rowDelta, lstEpisode.Height);
            lstEpisode.Location = new Point(episodeX + episodeOffset, lstEpisode.Top);
            lblTitLastViewed.Location = new Point(episodeX + episodeOffset, lblTitLastViewed.Top);
            lblTitLastViewed.Size = new Size(episodeBaseWidth + rowDelta, lblTitLastViewed.Height);
            lblLastViewed.Location = new Point(episodeX + episodeOffset, lblLastViewed.Top);
            lblLastViewed.Size = new Size(episodeBaseWidth + rowDelta, lblLastViewed.Height);

            // Row Favs
            const int favBaseWidth = 162;
            const int favbtnWidth = 60;
            const int favX = 174;
            const int refX = 240;
            const int delX = 276;
            int favOffset = rowDelta;
            lblTitFavs.Size = new Size(favBaseWidth + rowDelta, lblTitFavs.Height);
            lblTitFavs.Location = new Point(favX + favOffset, lblTitFavs.Top);
            lstFavs.Size = new Size(favBaseWidth + rowDelta, lstFavs.Height);
            lstFavs.Location = new Point(favX + favOffset, lstFavs.Top);
            btnAddFavs.Size = new Size(favbtnWidth + (rowDelta / 2), btnAddFavs.Height);
            btnAddFavs.Location = new Point(favX + favOffset, btnAddFavs.Top);
            btnRefresh.Location = new Point(refX + favOffset + (rowDelta / 2), btnRefresh.Top);
            btnRemoveFavs.Size = new Size(favbtnWidth + (rowDelta / 2), btnRemoveFavs.Height);
            btnRemoveFavs.Location = new Point(delX + favOffset + (rowDelta / 2), btnRemoveFavs.Top);


            // Row Series
            const int serieBaseWidth = 162;
            pnlSeries.Size = new Size(serieBaseWidth + rowDelta, pnlSeries.Height);

            this.ResumeLayout(false);
            this.PerformLayout();
        }

        private void btnGetMoreInfo_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            TVShowInfo tsi = CurrentTVShow();
            if (tsi != null)
            {
                tabctlShow.Enabled = false;
                picMoreInfo.Etat = StatePictureBoxStates.Waiting;
                picMoreInfoInsist.Etat = StatePictureBoxStates.Waiting;
                new Thread(new ParameterizedThreadStart(LoadEpGuide)).Start(tsi);
            }
        }


        public void LoadEpGuide(object state)
        {
            TVShowInfo si = (TVShowInfo)state;
            try
            {
                if (!si.EpGuideLoaded)
                    si.EpGuideId = SelectGuide(si.Name);
                si.LoadEpGuide();
                si.LoadTVRage();
            }
            catch
            {
            }
            EndLoadEpGuide(si);
        }

        public void RefreshShowDesc(TVShowInfo ts)
        {
            bool infos = (ts.EpGuideLoaded && ts.TvRage != null && ts.TvRage.Loaded && !ts.TvRage.Broken);
            if (infos)
            {
                if (!tabctlShow.TabPages.Contains(tpageInfo))
                    tabctlShow.TabPages.Insert(0, tpageInfo);
                if (tabctlShow.TabPages.Contains(tpageMoreInfo))
                    tabctlShow.TabPages.Remove(tpageMoreInfo);
                if (tabctlShow.TabPages.Contains(tpageInsistMoreInfo))
                    tabctlShow.TabPages.Remove(tpageInsistMoreInfo);
            }
            else
            {
                if (tabctlShow.TabPages.Contains(tpageInfo))
                    tabctlShow.TabPages.Remove(tpageInfo);
                if (ts.EpGuideId == TVShowInfo.NO_EPGUIDE)
                {
                    if (!tabctlShow.TabPages.Contains(tpageInsistMoreInfo))
                        tabctlShow.TabPages.Add(tpageInsistMoreInfo);
                    if (tabctlShow.TabPages.Contains(tpageMoreInfo))
                        tabctlShow.TabPages.Remove(tpageMoreInfo);
                }
                else
                {
                    if (!tabctlShow.TabPages.Contains(tpageMoreInfo))
                        tabctlShow.TabPages.Add(tpageMoreInfo);
                    if (tabctlShow.TabPages.Contains(tpageInsistMoreInfo))
                        tabctlShow.TabPages.Remove(tpageInsistMoreInfo);
                }
            }
            if (infos)
            {
                lblAirings.Text = ts.TvRage.SayAirings;
                lblTitLastAired.Visible = !String.IsNullOrEmpty(ts.TvRage.SayLastAired);
                lblLastAired.Text = ts.TvRage.SayLastAired;
                lblTitNextAired.Visible = !String.IsNullOrEmpty(ts.TvRage.SayNextAired);
                lblNextAired.Text = ts.TvRage.SayNextAired;
                lblGenres.Text = ts.TvRage.SayGenres;
            }
            tabctlShow.SelectedIndex = 0;
            tabctlShow.Visible = true;
            tabctlShow.Enabled = true;
            lblLastViewed.Text = ts.LastViewed;
            lblTitLastViewed.Visible = !String.IsNullOrEmpty(ts.LastViewed);
            lblLastViewed.Visible = !String.IsNullOrEmpty(ts.LastViewed);
            txtShowDesc.Text = ts.Description;
        }


        public void EndLoadEpGuide(TVShowInfo ti)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new TupleShowHandler(EndLoadEpGuide), new object[] { ti });
                return;
            }
            picMoreInfo.Etat = StatePictureBoxStates.None;
            picMoreInfoInsist.Etat = StatePictureBoxStates.None;
            RefreshShowDesc(ti);
        }
        private void btnViewIMDB_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            TVShowInfo tsi = CurrentTVShow();
            if (tsi != null && !String.IsNullOrEmpty(tsi.ImdbId))
            {
                Process.Start("http://www.imdb.com/title/" + tsi.ImdbId);
            }
        }

        private void btnViewTVRage_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            TVShowInfo tsi = CurrentTVShow();
            if (tsi != null && !String.IsNullOrEmpty(tsi.TvRageId))
            {
                Process.Start(TvRageEntry.URL + tsi.TvRageId);
            }
        }
        public TVShowInfo CurrentTVShow()
        {
            if (lstSerie.SelectedIndex > -1)
                return (TVShowInfo)lstSerie.SelectedItem;
            if (lstFavs.SelectedIndex > -1)
                return (TVShowInfo)lstFavs.SelectedItem;
            return null;
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(txtSearch.Text))
            {
                statePictureBox1.Etat = EricUtility.Windows.Forms.StatePictureBoxStates.Waiting;
                if (!String.IsNullOrEmpty(oldLetter))
                    pnlLetters.Controls["btn" + oldLetter].Enabled = true;
                oldLetter = null;

                lstFavs.SelectedIndex = -1;
                lstSerie.Items.Clear();
                lstSeason.Items.Clear();
                lstEpisode.Items.Clear();
                lstWebSite.Items.Clear();
                foreach (CheckBox c in btnKnowns.Values)
                {
                    c.Enabled = false;
                    c.Checked = false;
                }
                btnMagic.Enabled = false;
                btnAddFavs.Enabled = false;
                btnRemoveFavs.Enabled = false;
                btnRefresh.Enabled = false;
                lstMirror.Items.Clear();
                lstLink.Items.Clear();
                tabctlShow.Visible = false;
                lblTitLastViewed.Visible = false;
                lblLastViewed.Visible = false;
                grpEpisodeDesc.Visible = false;
                Enabled = false;
                new Thread(new ParameterizedThreadStart(LoadLetter)).Start(new SearchInfo(txtSearch.Text));
            }

        }

        private void txtSearch_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                btnSearch_Click(sender, e);
        }
    }
}
